package com.wzh.ojbackendquestionservice.listener;

import com.rabbitmq.client.Channel;
import com.wzh.ojModel.model.entity.QuestionSubmit;
import com.wzh.ojbackendserviceclient.service.JudgeFeignClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import static com.wzh.ojCommon.constant.RabbitMqConstant.QUESTION_SUBMIT_QUEUE;

/**
 * @author wzh
 */
@Component
@Slf4j
public class MessageListener {
    /**
     * 注意，如果未提前在rabbitMq中创建队列的话 生产者是懒加载机制，而消费者是饿汉式加载机制
     * 在此情况下从而导致报错
     * @return
     */

    @Resource
    private JudgeFeignClient judgeFeignClient;

    @Resource
    private RedisTemplate<String,String> redisTemplate;

    private static final String CONSUME_QUESTION_SUBMIT_SUCCESS_INFO="abbitmq:question:submit:id:";

    @RabbitListener(queuesToDeclare = {@Queue(QUESTION_SUBMIT_QUEUE)})
    public QuestionSubmit receiveSubmitId(Long questionSubmitId, Message message, Channel channel) {

        try {
            String var = redisTemplate.opsForValue().get(CONSUME_QUESTION_SUBMIT_SUCCESS_INFO + questionSubmitId);
            if (var!=null){
                log.info("重复消费{}"+questionSubmitId);
                return null;
            }
            QuestionSubmit questionSubmit = judgeFeignClient.doJudge(questionSubmitId);
            log.info("消费者消费消息,消息为:"+questionSubmitId);
            /**
             * 没有异常就确认消息
             * deliverTag:当前消息在队列中的索引
             * multiple:为true的话就是批量确认
             */
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            redisTemplate.opsForValue().set(CONSUME_QUESTION_SUBMIT_SUCCESS_INFO+questionSubmitId,String.valueOf(questionSubmitId),30, TimeUnit.MINUTES);
            return questionSubmit;
        } catch (Exception e) {
            /**
             * 有异常则拒收消息
             * basicNack(long deliveryTag, boolean multiple, boolean requeue)
             *               requeue:true为将消息重返当前消息队列,重新发送给消费者;
             *                       false将消息丢弃
             */
            log.info("消费者消费消息出现异常："+e.getMessage());
            try {
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
            throw new RuntimeException(e);
        }
    }
}
